home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / prof / ds5000.md / _mcount.c next >
C/C++ Source or Header  |  1989-10-30  |  6KB  |  217 lines

  1. /* 
  2.  * _mcount.c --
  3.  *
  4.  *    This is the code for the routine mcount.  mcount is the routine
  5.  *    called at the beginning of each procedure if it the code has
  6.  *    been compiled with the -p option to cc.
  7.  *
  8.  *    NB: The compiler compiles this procedure into something called
  9.  *    "_mcount" which we massage back into "mcount" (see the Makefile).
  10.  *
  11.  * Copyright 1986, 1988 Regents of the University of California
  12.  * Permission to use, copy, modify, and distribute this
  13.  * software and its documentation for any purpose and without
  14.  * fee is hereby granted, provided that the above copyright
  15.  * notice appear in all copies.  The University of California
  16.  * makes no representations about the suitability of this
  17.  * software for any purpose.  It is provided "as is" without
  18.  * express or implied warranty.
  19.  */
  20.  
  21. #ifndef lint
  22. static char rcsid[] = "$Header: /sprite/src/kernel/prof/ds3100.md/RCS/_mcount.c,v 1.2 89/10/30 20:46:38 rab Exp Locker: rab $ SPRITE (DECWRL)";
  23. #endif
  24.  
  25.  
  26. #include "sprite.h"
  27. #include "prof.h"
  28. #include "profInt.h"
  29. #include "sync.h"
  30. #include "sys.h"
  31. #include "dbg.h"
  32.  
  33. /*
  34.  * Boolean to prevent recursion in mcount.  This would only work
  35.  * on a uniprocessor, and can be eliminated if you never compile
  36.  * this file with -p.
  37.  *
  38. static Boolean inMcount = FALSE;
  39.  *  
  40.  */
  41.  
  42. /*
  43.  * There is a critical section when mcount does a pseudo-alloc
  44.  * of the storage for its arcs.
  45.  */
  46.  
  47. #ifndef lint
  48. static int    mcountMutex;
  49. #endif
  50.  
  51.  
  52. /*
  53.  *----------------------------------------------------------------------
  54.  *
  55.  * mcount --
  56.  *
  57.  *    A call to this routine is inserted by the compiler at the
  58.  *    beginning of every routine. (Use the -p option to cc.)
  59.  *    This looks up the call stack a bit to determine which arc
  60.  *    of the call graph is being executed.  A call graph arc represents
  61.  *    one routine calling another.  The routine with the call to mcount
  62.  *    is the callee of the arc, its caller (mcount's "grandparent")
  63.  *    is the caller of the arc.  An execution count is kept for each
  64.  *    arc.  The counts are dumped out and analyzed by the gprof program.
  65.  *
  66.  * Results:
  67.  *    None.
  68.  *
  69.  * Side effects:
  70.  *    Increment a counter corresponding to the call graph arc.
  71.  *
  72.  *----------------------------------------------------------------------
  73.  */
  74.  
  75. void
  76. mcount()
  77. {
  78. #ifdef notdef
  79.     register unsigned int calleePC;    /* PC of instr. that called mcount */
  80.     register unsigned int callerPC;    /* PC of instr. that called mcount's 
  81.                      * caller */
  82.     register unsigned int instructionNumber;    /* Index into profArcIndex */
  83.     register ProfRawArc *arcPtr;    /* Pointer to arc data storage */
  84.  
  85.     if (!profEnabled) {
  86.     return;
  87.     }
  88.  
  89. /*
  90.     if (inMcount) {
  91.     return;
  92.     } else {
  93.     inMcount = TRUE;
  94.     }
  95. */
  96.  
  97.     /*
  98.      * Get the PC that was saved after the jsr mcount instruction.
  99.      * This is done by getting our frame pointer and then looking
  100.      * next to it on the stack for the saved PC.
  101.      * The saved PC identifies the caller of mcount and the callee
  102.      * of the call graph arc.
  103.      */
  104.  
  105.     calleePC  = Prof_ThisPC( Prof_ThisFP() );
  106.  
  107.  
  108.     /*
  109.      * Get the PC that was saved after the jsr foo instruction.
  110.      * This PC identifies the caller of foo and the caller in
  111.      * the call graph arc.
  112.      */
  113.  
  114.     callerPC = Prof_ThisPC( Prof_CallerFP() );
  115.  
  116.     /*
  117.      * Use the PC of the jsr foo instruction as an index into the
  118.      * index of stored arcs.  There should only be one call instruction
  119.      * that corresponds to the index.
  120.      *
  121.      * Go from PC to instruction number by subracting off the base
  122.      * PC and dividing by the instruction size (2 bytes).
  123.      */
  124.  
  125.     instructionNumber =  (callerPC) >> PROF_ARC_SHIFT;
  126.     if (instructionNumber > profArcIndexSize) {
  127.     printf(
  128.           "_mcount: Index (%d) exceeds bounds (%d) of index array.\n",
  129.           instructionNumber, profArcIndexSize);
  130.     goto exit;
  131.     }
  132.  
  133.     /*
  134.      * Check to see if arcPtr equals an unused value (which is 0 because
  135.      * profArcIndex is initialized with Byte_Zero in Prof_Start).
  136.      */
  137.  
  138.     arcPtr = profArcIndex[instructionNumber];
  139.     if (arcPtr == (ProfRawArc *) 0) {
  140.  
  141. #ifdef DEBUG
  142.     printf( "mcount: 1 callerPC = %x(%d), calleePC = %x\n",
  143.                 callerPC, instructionNumber, calleePC);
  144.     /* DBG_CALL; */
  145. #endif DEBUG
  146.  
  147.     /*
  148.      * First time call graph arc has been traversed.  Allocate arc
  149.      * storage from the arcList and initialize it.  This is locked
  150.      * to prevent the scheduler from interrupting the allocation
  151.      * and initialization.
  152.      */
  153.  
  154.     if (profArcListFreePtr >= profArcListEndPtr) {
  155.         profEnabled = FALSE;
  156.         printf( 
  157.             "_mcount: No more arcs, stopping profiling\n");
  158.     } else {
  159.  
  160.         MASTER_LOCK(*mcountMutex);
  161.  
  162.         arcPtr = profArcListFreePtr;
  163.         profArcListFreePtr++;
  164.         profArcIndex[instructionNumber] = arcPtr;
  165.         arcPtr->calleePC = calleePC;
  166.         arcPtr->count    = 1;
  167.         arcPtr->link     = (ProfRawArc *)NIL;
  168.  
  169.         MASTER_UNLOCK(mcountMutex);
  170.     }
  171.     goto exit;
  172.     }
  173.  
  174.     while (arcPtr->calleePC != calleePC) {
  175.     /*
  176.      * Loop through the list of callee's for this caller.
  177.      */
  178.  
  179.     if (arcPtr->link == (ProfRawArc *)NIL) {
  180.  
  181.         /*
  182.          *  Allocate, link, and initialize another arc storage unit.
  183.          */
  184. #ifdef DEBUG
  185.         printf( 
  186.             "mcount 2 callerPC = %x(%d), calleePC = %x\n",
  187.             callerPC, instructionNumber, calleePC);
  188.     /* DBG_CALL; */
  189. #endif DEBUG
  190.  
  191.         if (profArcListFreePtr >= profArcListEndPtr) {
  192.         printf( "_mcount: No more arcs\n");
  193.         } else {
  194.         MASTER_LOCK(mcountMutex);
  195.  
  196.         arcPtr->link = profArcListFreePtr;
  197.         profArcListFreePtr++;
  198.  
  199.         arcPtr = arcPtr->link;
  200.         arcPtr->calleePC    = calleePC;
  201.         arcPtr->count        = 1;
  202.         arcPtr->link        = (ProfRawArc *) NIL;
  203.  
  204.         MASTER_UNLOCK(mcountMutex);
  205.         }
  206.         goto exit;
  207.     }
  208.     arcPtr = arcPtr->link;
  209.     }
  210.     arcPtr->count++;
  211.  
  212. exit:
  213. #endif
  214.     /* inMcount = FALSE; */
  215.     return;
  216. }
  217.